#pragma once
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <atomic>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/select.h>
#include "rga/rga.h"
#include "rga/im2d.hpp"
// #include "rga/im2d_type.h"
// #include "rga/im2d_buffer.h"
// #include "rga/im2d_common.h"
#include "rga/RgaUtils.h"
#include "drm/xf86drm.h"
#include "drm/xf86drmMode.h"
#include "drm/libdrm/drm_fourcc.h"
#include "log/log.h"

class Player {
private:
    typedef struct {
        uint32_t fb_id;
        int buf_fd;  // 文件描述符
        void *ptr;
        uint64_t size;
        uint32_t pitch;
        uint32_t handle;
        uint32_t width;
        uint32_t height;
    } drm_buf_obj_t;

public:
    Player(uint32_t width, uint32_t height, uint32_t format = DRM_FORMAT_YUYV)
            : m_width(width), m_height(height), m_drm_format(format)
            { init(); };
    ~Player() { deinit(); }

    int init() {
        m_loop_run = true;
        drm_init();
        rga_init();
        return 0;
    }

    int deinit() {
        m_loop_run = false;
        rga_deinit();
        drm_deinit();
        return 0;
    }

    int write_image(RgaSURF_FORMAT format, uint8_t* buffer);
    int player_image(uint32_t wait_time = 1);

private:
    int drm_init();
    int drm_deinit();
    int drm_get_bpp(uint32_t format) const;
    int drm_create_fb(drm_buf_obj_t* bo);
    int drm_destroy_fb(drm_buf_obj_t* bo);

    int rga_init(RgaSURF_FORMAT dst_format = RK_FORMAT_YUYV_422);
    int rga_cvtcolor(RgaSURF_FORMAT format, uint8_t* buffer);
    int rga_deinit();

private:
    std::atomic_bool m_loop_run;

    uint32_t m_width;
    uint32_t m_height;

    // rga
    RgaSURF_FORMAT m_rga_dst_format;
    rga_buffer_t m_rga_src = {}, m_rga_dst = {};
    im_rect m_rga_src_rect = {}, m_rga_dst_rect = {};
    rga_buffer_handle_t m_rga_src_handle = {}, m_rga_dst_handle[3] = {};

    // drm
    int m_fd{-1};
    drmModeRes *m_res{nullptr};
    drmModeCrtc* m_crtc{nullptr};
    uint32_t m_crtc_id{};
    drmModeConnector *m_conn{nullptr};
    uint32_t m_conn_id{};
    uint32_t m_conn_mode_id{};

    drmEventContext m_event{};
    drm_buf_obj_t m_buf_obj[3]{};
    uint32_t m_drm_format{};
};